#pragma once
#include<vector>
#include<semaphore.h>
#define defaultsize 5

template<class T>
class RingQueue
{
public:
   
    RingQueue(int size = defaultsize)
        :_size(size),_ringqueue(size),_c_step(0),_p_step(0)
    {
        sem_init(&_data,0,0);
        sem_init(&_space,0,size);
        pthread_mutex_init(&_c_mutex,nullptr);
        pthread_mutex_init(&_p_mutex,nullptr);
    }

    void push(const T& in)
    {
        sem_wait(&_space);
        pthread_mutex_lock(&_p_mutex);
        _ringqueue[_p_step] = in;
        _p_step++;
        _p_step %= _size;
        pthread_mutex_unlock(&_p_mutex);
        sem_post(&_data);
    }

    void pop(T* out)
    {
        sem_wait(&_data);
        pthread_mutex_lock(&_c_mutex);
        *out = _ringqueue[_c_step];
        _c_step++;
        _c_step %= _size;
        pthread_mutex_unlock(&_c_mutex);
        sem_post(&_space);
    }

private:
    vector<T> _ringqueue;
    int _size;

    sem_t _data;
    sem_t _space;

    int _c_step;
    int _p_step;

    pthread_mutex_t _c_mutex;
    pthread_mutex_t _p_mutex;

};